package nz.jdbcwrapper;

import java.sql.ParameterMetaData;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Ref;
import java.sql.Array;
import java.sql.Types;
import java.sql.Statement;

import java.io.InputStream;
import java.io.Reader;

import java.math.BigDecimal;
import java.net.URL;
import java.util.Calendar;

class WrapperPreparedStatement extends WrapperStatement implements PreparedStatement
{
  private final PreparedStatement preparedStatement;

  WrapperPreparedStatement(Data data,
                           Statistic statistic,
                           PreparedStatement preparedStatement)
  {
    super(data, statistic, preparedStatement);
    this.preparedStatement = preparedStatement;
  }

  /**
   * Executes the SQL query in this <code>PreparedStatement</code> object
   * and returns the result set generated by the query.
   *
   * @return a <code>ResultSet</code> object that contains the data produced by the
   * query; never <code>null</code>
   * @exception SQLException if a database access error occurs
   */
  public ResultSet executeQuery() throws SQLException
  {
    long start = 0;
    long duration = Long.MIN_VALUE;
    long key = 0L;

    if (data.trace >= 3)
      key = Util.traceBegin(prefix + " executeQuery()");

    SQLException excp;

    try
    {
      start = System.currentTimeMillis();
      ResultSet resultSet = preparedStatement.executeQuery();
      duration = System.currentTimeMillis() - start;
      WrapperResultSet result = WrapperResultSet.build(data,this, statistic, prefix, resultSet);

      if (data.trace >= 3)
        Util.traceEnd(key, result.prefix);

      return result;
    }
    catch (SQLException e)
    {
      duration = System.currentTimeMillis() - start;
      if (data.trace >= 3)
        Util.traceEnd(key, e);
      excp = e;
    }
    finally
    {
      if (duration == Long.MIN_VALUE)
        duration = System.currentTimeMillis() - start;
      statistic.execution(System.currentTimeMillis() - start);
      checkWarnings();
    }
    throw excp;
  }

  /**
   * Executes the SQL INSERT, UPDATE or DELETE statement
   * in this <code>PreparedStatement</code> object.
   * In addition,
   * SQL statements that return nothing, such as SQL DDL statements,
   * can be executed.
   *
   * @return either the row count for INSERT, UPDATE or DELETE statements;
   * or 0 for SQL statements that return nothing
   * @exception SQLException if a database access error occurs
   */
  public int executeUpdate() throws SQLException
  {
    long start = 0;
    long duration = Long.MIN_VALUE;
    long key = 0L;
    SQLException excp;

    if (data.trace >= 3)
      key = Util.traceBegin(prefix + " executeUpdate()");

    try
    {
      start = System.currentTimeMillis();
      int result = preparedStatement.executeUpdate();
      duration = System.currentTimeMillis() - start;

      if (data.trace >= 3)
        Util.traceEnd(key, String.valueOf(result));

      return result;
    }
    catch (SQLException e)
    {
      duration = System.currentTimeMillis() - start;

      if (data.trace >= 3)
        Util.traceEnd(key, e);

      excp = e;
    }
    finally
    {
      if (duration == Long.MIN_VALUE)
        duration = System.currentTimeMillis() - start;

      if (statistic != null)
        statistic.execution(duration);
      checkWarnings();
    }

    throw excp;
  }

  /**
   * Sets the designated parameter to SQL <code>NULL</code>.
   *
   * <P><B>Note:</B> You must specify the parameter's SQL type.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
   * @exception SQLException if a database access error occurs
   */
  public void setNull(int parameterIndex, int sqlType) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setNull(" + parameterIndex + ", " + sqlType + ")");

    try
    {
      preparedStatement.setNull(parameterIndex, sqlType);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>boolean</code> value.
   * The driver converts this
   * to an SQL <code>BIT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setBoolean(int parameterIndex, boolean x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setBoolean(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setBoolean(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>byte</code> value.
   * The driver converts this
   * to an SQL <code>TINYINT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setByte(int parameterIndex, byte x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setByte(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setByte(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>short</code> value.
   * The driver converts this
   * to an SQL <code>SMALLINT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setShort(int parameterIndex, short x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setShort(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setShort(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>int</code> value.
   * The driver converts this
   * to an SQL <code>INTEGER</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setInt(int parameterIndex, int x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setInt(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setInt(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>long</code> value.
   * The driver converts this
   * to an SQL <code>BIGINT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setLong(int parameterIndex, long x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setLong(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setLong(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>float</code> value.
   * The driver converts this
   * to an SQL <code>FLOAT</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setFloat(int parameterIndex, float x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setFloat(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setFloat(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>double</code> value.
   * The driver converts this
   * to an SQL <code>DOUBLE</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setDouble(int parameterIndex, double x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setDouble(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setDouble(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a <code>java.math.BigDecimal</code> value.
   * The driver converts this to an SQL <code>NUMERIC</code> value when
   * it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setBigDecimal(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setBigDecimal(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java <code>String</code> value.
   * The driver converts this
   * to an SQL <code>VARCHAR</code> or <code>LONGVARCHAR</code> value
   * (depending on the argument's
   * size relative to the driver's limits on <code>VARCHAR</code> values)
   * when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setString(int parameterIndex, String x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setString(" + parameterIndex + ", " + Util.toString(x) + ")");

    try
    {
      preparedStatement.setString(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a Java array of bytes.  The driver converts
   * this to an SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code>
   * (depending on the argument's size relative to the driver's limits on
   * <code>VARBINARY</code> values) when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setBytes(int parameterIndex, byte x[]) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setBytes(" +
                            parameterIndex + ", " +
                            Util.toString(x) + ")");

    try
    {
      preparedStatement.setBytes(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a <code<java.sql.Date</code> value.
   * The driver converts this
   * to an SQL <code>DATE</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setDate(int parameterIndex, java.sql.Date x)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setDate(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setDate(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a <code>java.sql.Time</code> value.
   * The driver converts this
   * to an SQL <code>TIME</code> value when it sends it to the database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setTime(int parameterIndex, java.sql.Time x)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setTime(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setTime(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to a <code>java.sql.Timestamp</code> value.
   * The driver
   * converts this to an SQL <code>TIMESTAMP</code> value when it sends it to the
   * database.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setTimestamp(int parameterIndex, java.sql.Timestamp x)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setTimestamp(" + parameterIndex + ", " + x + ")");

    try
    {
      preparedStatement.setTimestamp(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given input stream, which will have
   * the specified number of bytes.
   * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.InputStream</code>. Data will be read from the stream
   * as needed until end-of-file is reached.  The JDBC driver will
   * do any necessary conversion from ASCII to the database char format.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the Java input stream that contains the ASCII parameter value
   * @param length the number of bytes in the stream
   * @exception SQLException if a database access error occurs
   */
  public void setAsciiStream(int parameterIndex, InputStream x, int length)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setAsciiStream(" +
                            parameterIndex + ", " + Util.toString(x) + ", " + length + ")");

    try
    {
      preparedStatement.setAsciiStream(parameterIndex, x, length);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given input stream, which will have
   * the specified number of bytes.
   * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.InputStream</code> object. The data will be read from the stream
   * as needed until end-of-file is reached.  The JDBC driver will
   * do any necessary conversion from UNICODE to the database char format.
   * The byte format of the Unicode stream must be Java UTF-8, as
   * defined in the Java Virtual Machine Specification.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java input stream which contains the
   * UNICODE parameter value
   * @param length the number of bytes in the stream
   * @exception SQLException if a database access error occurs
   * @deprecated
   */
  public void setUnicodeStream(int parameterIndex, InputStream x,
                        int length) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setUnicodeStream(" +
                            parameterIndex + ", " + Util.toString(x) + ", " + length + ")");

    try
    {
      preparedStatement.setUnicodeStream(parameterIndex, x, length);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given input stream, which will have
   * the specified number of bytes.
   * When a very large binary value is input to a <code>LONGVARBINARY</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.InputStream</code> object. The data will be read from the stream
   * as needed until end-of-file is reached.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the java input stream which contains the binary parameter value
   * @param length the number of bytes in the stream
   * @exception SQLException if a database access error occurs
   */
  public void setBinaryStream(int parameterIndex, InputStream x,
                       int length) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setBinaryStream(" +
                            parameterIndex + ", " + Util.toString(x) + ", " + length + ")");

    try
    {
      preparedStatement.setBinaryStream(parameterIndex, x, length);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Clears the current parameter values immediately.
   * <P>In general, parameter values remain in force for repeated use of a
   * statement. Setting a parameter value automatically clears its
   * previous value.  However, in some cases it is useful to immediately
   * release the resources used by the current parameter values; this can
   * be done by calling the method <code>clearParameters</code>.
   *
   * @exception SQLException if a database access error occurs
   */
  public void clearParameters() throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " clearParameters()");

    try
    {
      preparedStatement.clearParameters();
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  //----------------------------------------------------------------------
  // Advanced features:

  /**
   * <p>Sets the value of the designated parameter with the given object. The second
   * argument must be an object type; for integral values, the
   * <code>java.lang</code> equivalent objects should be used.
   *
   * <p>The given Java object will be converted to the given targetSqlType
   * before being sent to the database.
   *
   * If the object has a custom mapping (is of a class implementing the
   * interface <code>SQLData</code>),
   * the JDBC driver should call the method <code>SQLData.writeSQL</code> to write it
   * to the SQL data stream.
   * If, on the other hand, the object is of a class implementing
   * Ref, Blob, Clob, Struct,
   * or Array, the driver should pass it to the database as a value of the
   * corresponding SQL type.
   *
   * <p>Note that this method may be used to pass datatabase-
   * specific abstract data types.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
   * sent to the database. The scale argument may further qualify this type.
   * @param scale for java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types,
   *          this is the number of digits after the decimal point.  For all other
   *          types, this value will be ignored.
   * @exception SQLException if a database access error occurs
   * @see Types
   */
  public void setObject(int parameterIndex, Object x, int targetSqlType, int scale)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setObject(" +
                            parameterIndex + ", " +
                            Util.toString(x) + ", " +
                            targetSqlType + ", " + scale + ")");

    try
    {
      preparedStatement.setObject(parameterIndex, x, targetSqlType, scale);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the value of the designated parameter with the given object.
   * This method is like the method <code>setObject</code>
   * above, except that it assumes a scale of zero.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @param targetSqlType the SQL type (as defined in java.sql.Types) to be
   *                      sent to the database
   * @exception SQLException if a database access error occurs
   */
  public void setObject(int parameterIndex, Object x, int targetSqlType)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setObject(" +
                            parameterIndex + ", " +
                            Util.toString(x) + ", " +
                            targetSqlType + ")");

    try
    {
      preparedStatement.setObject(parameterIndex, x, targetSqlType);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * <p>Sets the value of the designated parameter using the given object.
   * The second parameter must be of type <code>Object</code>; therefore, the
   * <code>java.lang</code> equivalent objects should be used for built-in types.
   *
   * <p>The JDBC specification specifies a standard mapping from
   * Java <code>Object</code> types to SQL types.  The given argument
   * will be converted to the corresponding SQL type before being
   * sent to the database.
   *
   * <p>Note that this method may be used to pass datatabase-
   * specific abstract data types, by using a driver-specific Java
   * type.
   *
   * If the object is of a class implementing the interface <code>SQLData</code>,
   * the JDBC driver should call the method <code>SQLData.writeSQL</code>
   * to write it to the SQL data stream.
   * If, on the other hand, the object is of a class implementing
   * Ref, Blob, Clob, Struct,
   * or Array, then the driver should pass it to the database as a value of the
   * corresponding SQL type.
   *
   * This method throws an exception if there is an ambiguity, for example, if the
   * object is of a class implementing more than one of the interfaces named above.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the object containing the input parameter value
   * @exception SQLException if a database access error occurs
   */
  public void setObject(int parameterIndex, Object x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setObject(" +
                            parameterIndex + ", " +
                            Util.toString(x) + ")");

    try
    {
      preparedStatement.setObject(parameterIndex, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Executes any kind of SQL statement.
   * Some prepared statements return multiple results; the <code>execute</code>
   * method handles these complex statements as well as the simpler
   * form of statements handled by the methods <code>executeQuery</code>
   * and <code>executeUpdate</code>.
   *
   * @exception SQLException if a database access error occurs
   * @see Statement#execute
   */
  public boolean execute() throws SQLException
  {
    long start = 0;
    long duration = Long.MIN_VALUE;
    long key = 0L;
    SQLException excp;

    if (data.trace >= 3)
      key = Util.traceBegin(prefix + " execute()");

    try
    {
      start = System.currentTimeMillis();
      boolean result = preparedStatement.execute();
      duration = System.currentTimeMillis() - start;

      if (data.trace >= 3)
        Util.traceEnd(key, String.valueOf(result));

      return result;
    }
    catch (SQLException e)
    {
      duration = System.currentTimeMillis() - start;

      if (data.trace >= 3)
        Util.traceEnd(key, e);

      excp = e;
    }
    finally
    {
      if (duration == Long.MIN_VALUE)
        duration = System.currentTimeMillis() - start;

      if (statistic != null)
        statistic.execution(duration);
      checkWarnings();
    }

    throw excp;
  }

  //--------------------------JDBC 2.0-----------------------------

  /**
   * Adds a set of parameters to this <code>PreparedStatement</code>
   * object's batch of commands.
   *
   * @exception SQLException if a database access error occurs
   * @see Statement#addBatch
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void addBatch() throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " addBatch()");

    try
    {
      preparedStatement.addBatch();
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given <code>Reader</code>
   * object, which is the given number of characters long.
   * When a very large UNICODE value is input to a <code>LONGVARCHAR</code>
   * parameter, it may be more practical to send it via a
   * <code>java.io.Reader</code> object. The data will be read from the stream
   * as needed until end-of-file is reached.  The JDBC driver will
   * do any necessary conversion from UNICODE to the database char format.
   *
   * <P><B>Note:</B> This stream object can either be a standard
   * Java stream object or your own subclass that implements the
   * standard interface.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param reader the java reader which contains the UNICODE data
   * @param length the number of characters in the stream
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setCharacterStream(int parameterIndex,
       			  Reader reader,
			  int length) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setCharacterStream(" +
                            parameterIndex + ", " + (reader == null ? "<null reader>" : reader.getClass().getName()) + ", " + length + ")");

    try
    {
      preparedStatement.setCharacterStream(parameterIndex, reader, length);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given
   *  <code>REF(&lt;structured-type&gt;)</code> value.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x an SQL <code>REF</code> value
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setRef (int i, Ref x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setRef(" + i + ", " + Util.toString(x) + ")");

    try
    {
      preparedStatement.setRef (i, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given
   *  <code>Blob</code> object.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x a <code>Blob</code> object that maps an SQL <code>BLOB</code> value
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setBlob (int i, Blob x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setBlob(" + i + ", " + Util.toString(x) + ")");

    try
    {
      preparedStatement.setBlob (i, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given
   *  <code>Clob</code> object.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x a <code>Clob</code> object that maps an SQL <code>CLOB</code> value
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setClob (int i, Clob x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setClob(" + i + ", " + Util.toString(x) + ")");

    try
    {
      preparedStatement.setClob (i, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given
   *  <code>Array</code> object.
   * Sets an Array parameter.
   *
   * @param i the first parameter is 1, the second is 2, ...
   * @param x an <code>Array</code> object that maps an SQL <code>ARRAY</code> value
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setArray (int i, Array x) throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setArray(" + i + ", " + Util.toString(x) + ")");

    try
    {
      preparedStatement.setArray (i, x);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Gets the number, types and properties of a <code>ResultSet</code>
   * object's columns.
   *
   * @return the description of a <code>ResultSet</code> object's columns
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public ResultSetMetaData getMetaData() throws SQLException
  {
    long key = 0L;
    if (data.trace >= 3)
      key = Util.traceBegin(prefix + " getMetaData()");
    try
    {
      WrapperResultSetMetaData result = new WrapperResultSetMetaData(
        data, prefix, preparedStatement.getMetaData());

      if (data.trace >= 3)
        Util.traceEnd(key, result.prefix);
      return result;
    }
    catch (SQLException e)
    {
      if (data.trace >= 3)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Date</code> value,
   * using the given <code>Calendar</code> object.  The driver uses
   * the <code>Calendar</code> object to construct an SQL <code>DATE</code> value,
   * which the driver then sends to the database.  With a
   * a <code>Calendar</code> object, the driver can calculate the date
   * taking into account a custom timezone.  If no
   * <code>Calendar</code> object is specified, the driver uses the default
   * timezone, which is that of the virtual machine running the application.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use
   *            to construct the date
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setDate(" + parameterIndex + ", " + x + ", " + Util.toString(cal) + ")");

    try
    {
      preparedStatement.setDate(parameterIndex, x, cal);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Time</code> value,
   * using the given <code>Calendar</code> object.  The driver uses
   * the <code>Calendar</code> object to construct an SQL <code>TIME</code> value,
   * which the driver then sends to the database.  With a
   * a <code>Calendar</code> object, the driver can calculate the time
   * taking into account a custom timezone.  If no
   * <code>Calendar</code> object is specified, the driver uses the default
   * timezone, which is that of the virtual machine running the application.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use
   *            to construct the time
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setTime(int parameterIndex, java.sql.Time x, Calendar cal)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setTime(" + parameterIndex + ", " + x + ", " + Util.toString(cal) + ")");

    try
    {
      preparedStatement.setTime(parameterIndex, x, cal);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to the given <code>java.sql.Timestamp</code> value,
   * using the given <code>Calendar</code> object.  The driver uses
   * the <code>Calendar</code> object to construct an SQL <code>TIMESTAMP</code> value,
   * which the driver then sends to the database.  With a
   * a <code>Calendar</code> object, the driver can calculate the timestamp
   * taking into account a custom timezone.  If no
   * <code>Calendar</code> object is specified, the driver uses the default
   * timezone, which is that of the virtual machine running the application.
   *
   * @param parameterIndex the first parameter is 1, the second is 2, ...
   * @param x the parameter value
   * @param cal the <code>Calendar</code> object the driver will use
   *            to construct the timestamp
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setTimestamp(" + parameterIndex + ", " + x + ", " + Util.toString(cal) + ")");

    try
    {
      preparedStatement.setTimestamp(parameterIndex, x, cal);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * Sets the designated parameter to SQL <code>NULL</code>.
   * This version of the method <code>setNull</code> should
   * be used for user-defined types and REF type parameters.  Examples
   * of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and
   * named array types.
   *
   * <P><B>Note:</B> To be portable, applications must give the
   * SQL type code and the fully-qualified SQL type name when specifying
   * a NULL user-defined or REF parameter.  In the case of a user-defined type
   * the name is the type name of the parameter itself.  For a REF
   * parameter, the name is the type name of the referenced type.  If
   * a JDBC driver does not need the type code or type name information,
   * it may ignore it.
   *
   * Although it is intended for user-defined and Ref parameters,
   * this method may be used to set a null parameter of any JDBC type.
   * If the parameter does not have a user-defined or REF type, the given
   * typeName is ignored.
   *
   *
   * @param paramIndex the first parameter is 1, the second is 2, ...
   * @param sqlType a value from <code>java.sql.Types</code>
   * @param typeName the fully-qualified name of an SQL user-defined type;
   *  ignored if the parameter is not a user-defined type or REF
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC
   *      2.0 API</a>
   */
  public void setNull (int paramIndex, int sqlType, String typeName)
    throws SQLException
  {
    long key = 0L;
    if (data.trace >= 4)
      key = Util.traceBegin(prefix + " setNull(" + paramIndex + ", " + sqlType + ", " + Util.toString(typeName) + ")");

    try
    {
      preparedStatement.setNull(paramIndex, sqlType, typeName);
      if (data.trace >= 4)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 4)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }
  /**
   * @see java.sql.PreparedStatement#getParameterMetaData()
   */
  public ParameterMetaData getParameterMetaData() throws SQLException
  {
    long key = 0L;

    if (data.trace >= 3)
      key = Util.traceBegin(prefix + " getParameterMetaData()");

    try
    {
      ParameterMetaData result = preparedStatement.getParameterMetaData();

      if (data.trace >= 3)
        Util.traceEnd(key, Util.toString(result));
      return result;
    }
    catch (SQLException e)
    {
      if (data.trace >= 3)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }

  /**
   * @see java.sql.PreparedStatement#setURL(int, URL)
   */
  public void setURL(int parameterIndex, URL x) throws SQLException
  {
    long key = 0L;

    if (data.trace >= 3)
      key = Util.traceBegin(prefix + " setURL(" + parameterIndex + ", " + Util.toString(x) + ")");

    try
    {
      preparedStatement.setURL(parameterIndex, x);

      if (data.trace >= 3)
        Util.traceEnd(key, (String)null);
    }
    catch (SQLException e)
    {
      if (data.trace >= 3)
        Util.traceEnd(key, e);
      throw e;
    }
    finally
    {
      checkWarnings();
    }
  }
  
//    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setAsciiStream(parameterIndex, x)");
//
//        try
//        {
//            preparedStatement.setAsciiStream(parameterIndex, x);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setAsciiStream(parameterIndex, x, length)");
//
//        try
//        {
//            preparedStatement.setAsciiStream(parameterIndex, x, length);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setBinaryStream(parameterIndex, x)");
//
//        try
//        {
//            preparedStatement.setBinaryStream(parameterIndex, x);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setBinaryStream(parameterIndex, x, length)");
//
//        try
//        {
//            preparedStatement.setBinaryStream(parameterIndex, x, length);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setBlob(parameterIndex, inputStream)");
//
//        try
//        {
//            preparedStatement.setBlob(parameterIndex, inputStream);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setBlob(parameterIndex, inputStream, length)");
//
//        try
//        {
//            preparedStatement.setBlob(parameterIndex, inputStream, length);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setCharacterStream(parameterIndex, reader)");
//
//        try
//        {
//            preparedStatement.setCharacterStream(parameterIndex, reader);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setCharacterStream(parameterIndex, reader, length)");
//
//        try
//        {
//            preparedStatement.setCharacterStream(parameterIndex, reader, length);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setClob(int parameterIndex, Reader reader) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setClob(parameterIndex, reader)");
//
//        try
//        {
//            preparedStatement.setClob(parameterIndex, reader);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setClob(int parameterIndex, Reader reader, long length) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setClob(parameterIndex, reader, length)");
//
//        try
//        {
//            preparedStatement.setClob(parameterIndex, reader, length);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setNCharacterStream(parameterIndex, value)");
//
//        try
//        {
//            preparedStatement.setNCharacterStream(parameterIndex, value);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setNCharacterStream(parameterIndex, value, length)");
//
//        try
//        {
//            preparedStatement.setNCharacterStream(parameterIndex, value, length);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setNClob(int parameterIndex, NClob value) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setNClob(parameterIndex, value)");
//
//        try
//        {
//            preparedStatement.setNClob(parameterIndex, value);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setNClob(int parameterIndex, Reader reader) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setNClob(parameterIndex, reader)");
//
//        try
//        {
//            preparedStatement.setNClob(parameterIndex, reader);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setNClob(parameterIndex, reader, length)");
//
//        try
//        {
//            preparedStatement.setNClob(parameterIndex, reader, length);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setNString(int parameterIndex, String value) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setNString(parameterIndex, value)");
//
//        try
//        {
//            preparedStatement.setNString(parameterIndex, value);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setRowId(int parameterIndex, RowId x) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setRowId(parameterIndex, x)");
//
//        try
//        {
//            preparedStatement.setRowId(parameterIndex, x);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
//
//    public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
//    {
//        long key = 0L;
//        if (data.trace >= 4)
//            key = Util.traceBegin(prefix + " setSQLXML(parameterIndex, xmlObject)");
//
//        try
//        {
//            preparedStatement.setSQLXML(parameterIndex, xmlObject);
//            if (data.trace >= 4)
//                Util.traceEnd(key, (String)null);
//        }
//        catch (SQLException e)
//        {
//            if (data.trace >= 4)
//                Util.traceEnd(key, e);
//            throw e;
//        }
//        finally
//        {
//            checkWarnings();
//        }
//    }
}
